package com.foreveross.mofang.serviceconsole.application.impl.core;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;
import javax.inject.Named;

import org.apache.commons.lang.StringUtils;
import org.dayatang.querychannel.Page;
import org.dayatang.querychannel.QueryChannelService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.foreveross.mofang.serviceconsole.application.core.NodeRegisterApplication;
import com.foreveross.mofang.serviceconsole.application.dto.NodeRegisterDTO;
import com.foreveross.mofang.serviceconsole.core.NodeRegister;
import com.foreveross.mofang.serviceconsole.infra.utils.PropertiesUtil;

/**
 * 结点报道基础设施实现层，用于结点的报道与界面上的一些查询之用。等最后一版本后，还要考虑鉴权等问 题
 * 
 * @author fb
 *
 */
@SuppressWarnings("unchecked")
@Named
@Transactional
public class NodeRegisterApplicationImpl implements NodeRegisterApplication {
	
	private final Logger log = LoggerFactory.getLogger(NodeRegisterApplicationImpl.class);
	
	@Inject
	private QueryChannelService queryChannel;
	
	@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
	public NodeRegisterDTO getNodeRegister(Long id) {
		NodeRegister nodeRegister = NodeRegister.load(NodeRegister.class, id);
		NodeRegisterDTO nodeRegisterDTO = new NodeRegisterDTO();
		// 将domain转成VO
		nodeRegisterDTO.domain2Dto(nodeRegister);
		nodeRegisterDTO.setId((java.lang.Long)nodeRegister.getId());
		return nodeRegisterDTO;
	}
	
	public Map<String, Object> nodeRegister(NodeRegisterDTO nodeRegisterDTO) {
		Map<String, Object> result = new HashMap<String, Object>();
		NodeRegister nodeRegister = new NodeRegister();
		nodeRegisterDTO.dto2Domain(nodeRegister);
		nodeRegister.save();
		nodeRegisterDTO.setId((java.lang.Long)nodeRegister.getId());
		// 这里要版本比较 ，反回当前adapter版本和其它一些信息
		
		return result;
	}
	
	public void heartbeat(String nodeSn) {
		try {
			NodeRegister.heartbeat(nodeSn);
		} catch (Exception e) {
			log.warn("nodeSn:{}不存，此节点从未联机注册!", nodeSn);
			throw new RuntimeException("心跳nodeSn未注册，结点不存在!", e);
		}
	}
	
	@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
	public Page<NodeRegisterDTO> pageQueryNewestNode(NodeRegisterDTO queryVo, int currentPage, int pageSize) {
		int registerHeartbeatInterval = Integer.parseInt(PropertiesUtil.getSystemValue("registerHeartbeatInterval")); 
		List<NodeRegisterDTO> result = new ArrayList<NodeRegisterDTO>();
		List<Object> conditionVals = new ArrayList<Object>();
	   	StringBuilder jpql = new StringBuilder("select _nodeRegister from NodeRegister _nodeRegister ");
	   	//jpql.append(" where _nodeRegister.registerDate = (select MAX(node.registerDate) from NodeRegister node where node.nodeSn = _nodeRegister.nodeSn) ");
	   	jpql.append(" where _nodeRegister.id = (select MAX(node.id) from NodeRegister node where node.nodeSn = _nodeRegister.nodeSn) ");
		
	   	if (StringUtils.isNotBlank(queryVo.getNodeSn())) {
	   		jpql.append(" and _nodeRegister.nodeSn like ?");
	   		conditionVals.add(MessageFormat.format("%{0}%", queryVo.getNodeSn()));
	   	}		
	
	   	if (StringUtils.isNotBlank(queryVo.getName())) {
	   		jpql.append(" and _nodeRegister.nodeName like ?");
	   		conditionVals.add(MessageFormat.format("%{0}%", queryVo.getName()));
	   	}		
	
	   	if (StringUtils.isNotBlank(queryVo.getIp())) {
	   		jpql.append(" and _nodeRegister.ip like ?");
	   		conditionVals.add(MessageFormat.format("%{0}%", queryVo.getIp()));
	   	}		
	
	   	if (StringUtils.isNotBlank(queryVo.getClientAdapterVersion())) {
	   		jpql.append(" and _nodeRegister.clientAdapterVersion like ?");
	   		conditionVals.add(MessageFormat.format("%{0}%", queryVo.getClientAdapterVersion()));
	   	}		
	
	   	if (StringUtils.isNotBlank(queryVo.getServerAdapterVersion())) {
	   		jpql.append(" and _nodeRegister.serverAdapterVersion like ?");
	   		conditionVals.add(MessageFormat.format("%{0}%", queryVo.getServerAdapterVersion()));
	   	}	
	   	
	   	if (queryVo.getIsOnLine() != null) {
	   		// 在线
	   		String operators = queryVo.getIsOnLine() ? " >= " : " < ";
	   		jpql.append(" and _nodeRegister.lastHeartbeatConnectionDate").append(operators).append(" ? ");
	   		conditionVals.add(org.apache.commons.lang3.time.DateUtils.addMinutes(new Date(), -registerHeartbeatInterval));
	   	}
	
	   	jpql.append(" ORDER BY _nodeRegister.id desc");
	   	
		Page<NodeRegister> pages = queryChannel.createJpqlQuery(jpql.toString()).setParameters(conditionVals).setPage(currentPage - 1, pageSize).pagedList();
				
		for (NodeRegister nodeRegister : pages.getData()) {
            NodeRegisterDTO nodeRegisterDTO = new NodeRegisterDTO();
            nodeRegisterDTO.domain2Dto(nodeRegister);
            nodeRegisterDTO.setIsOnLine(nodeRegister.isOline(registerHeartbeatInterval));
            result.add(nodeRegisterDTO);                                                                                        
        }
		
        return new Page<NodeRegisterDTO>(pages.getPageIndex(), pages.getResultCount(), pageSize, result);
	}

	@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
	public Page<NodeRegisterDTO> pageQueryNode(String nodeSn, int currentPage, int pageSize) {
		int registerHeartbeatInterval = Integer.parseInt(PropertiesUtil.getSystemValue("registerHeartbeatInterval")); 
		List<NodeRegisterDTO> result = new ArrayList<NodeRegisterDTO>();
		List<Object> conditionVals = new ArrayList<Object>();
	   	StringBuilder jpql = new StringBuilder("select _nodeRegister from NodeRegister _nodeRegister   where _nodeRegister.nodeSn = ? ");
	   	jpql.append(" ORDER BY _nodeRegister.id desc");
	   	
	   	conditionVals.add(nodeSn);
	   	
        Page<NodeRegister> pages = queryChannel.createJpqlQuery(jpql.toString()).setParameters(conditionVals).setPage(currentPage - 1, pageSize).pagedList();
        for (NodeRegister nodeRegister : pages.getData()) {
            NodeRegisterDTO nodeRegisterDTO = new NodeRegisterDTO();
            nodeRegisterDTO.domain2Dto(nodeRegister);
            nodeRegisterDTO.setIsOnLine(nodeRegister.isOline(registerHeartbeatInterval));
            result.add(nodeRegisterDTO);
        }
        
        return new Page<NodeRegisterDTO>(pages.getPageIndex(), pages.getResultCount(), pageSize, result);
	}
	
	
}
